// 10.5 泛型算法结构
/**
 * 算法所要求的迭代器操作可以分为5个迭代器类别（iterator category），如表10.5所示。
 * 每个算法都会对它的每个迭代器参数指明须提供哪类迭代器。[插图]
 * 1. 输入迭代器：只读不写，单遍扫描，只能递增
 * 2. 输出迭代器：只写不读，单遍扫描，只能递增
 * 3. 前向迭代器：可读写，多遍扫描，只能递增
 * 4. 双向迭代器：可读写，多变扫描，可递增递减
 * 5. 随机访问迭代器：可读写，多变扫描，支持全部迭代器运算
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include "../Chapter01/Sales_item.h"
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy, std::sort, std::unique, std::stable_sort, std::find_if, std::for_each;
using std::ostream, std::ref;
using std::transform, std::bind, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3;
using namespace std;

int main()
{
    // 10.5.1 五类迭代器
    // 对于向一个算法传递错误类别的迭代器的问题，很多编译器不会给出任何警告或提示。
    // 迭代器类别
    // 1. 输入迭代器只用于顺序访问。
    // 2. 我们只能向一个输出迭代器赋值一次。类似输入迭代器，输出迭代器只能用于单遍扫描算法。用作目的位置的迭代器通常都是输出迭代器。
    // 3. 前向迭代器（forward iterator）：可以读写元素。这类迭代器只能在序列中沿一个方向移动。
    // 4. 双向迭代器（bidirectional iterator）：可以正向/反向读写序列中的元素。除了支持所有前向迭代器的操作之外，
    //    双向迭代器还支持前置和后置递减运算符（--）。
    // 5. 随机访问迭代器（random-access iterator）：提供在常量时间内访问序列中任意元素的能力。

    // 10.5.2 算法形参模式
    // 理解这些参数规范对学习新算法很有帮助——通过理解参数的含义，你可以将注意力集中在算法所做的操作上。大多数算法具有如下4种形式之一：[插图]
    // 1. alg(beg, end, other args);
    // 2. alg(beg, end, dest, other args);
    // 3. alg(beg, end, beg2, other args);
    // 4. alg(beg, end, beg2, end2, other args);

    // 10.5.3 算法命名规范
    // 一些算法使用重载形式传递一个谓词
    // 接受谓词参数来代替<或==运算符的算法，以及那些不接受额外参数的算法，通常都是重载的函数。
    // 函数的一个版本用元素类型的运算符来比较元素；另一个版本接受一个额外谓词参数，来代替<或==：[插图]
    // 1. unique(beg, end);       // 使用 == 运算符比较元素
    // 2. unique(beg, end, comp); // 使用 comp 比较元素
    // _if版本的算法
    // 接受一个元素值的算法通常有另一个不同名的（不是重载的）版本，该版本接受一个谓词（参见10.3.1节，第344页）代替元素值。
    // 接受谓词参数的算法都有附加的_if前缀：[插图]
    // 1. find(beg, end, val);     // 查找输入范围中val第一次出现的位置
    // 2. find_if(beg, end, pred); // 查找第一个令pred为真的元素
    // 区分拷贝元素的版本和不拷贝的版本
    // 1. reverse(beg, end);            // 反转输入范围中元素的顺序
    // 2. reverse_copy(beg, end, dest); // 将元素按逆序拷贝到dest
    

    return 0;
}
